Skip to content

Optimize Lint/UselessAssign #603

Open
@nobodywasishere

Description

@nobodywasishere

Doing some basic performance metrics running ameba over the Crystal stdlib parser (src/compiler/crystal/syntax/parser.cr), most rules take a fraction of a second to run, except Lint/UselessAssign, which takes almost a second. Disabling this rule results in a significant boost in ameba performance (on this file). Granted, this isn't a great benchmark, esp since not all rules are in their worst-case performance wise, I think it's worth looking into if this rule can be optimized.

perf stats
Lint/UselessAssign: 0.850537000
Style/RedundantSelf: 0.040757000
Lint/Formatting: 0.010855000
Lint/Syntax: 0.009076000
Documentation/DocumentationAdmonition: 0.005054000
Lint/UnusedArgument: 0.005005000
Lint/ShadowedArgument: 0.004641000
Lint/MissingBlockArgument: 0.004399000
Lint/ShadowingOuterLocalVar: 0.003688000
Lint/SharedVarInFiber: 0.003485000
Lint/UnusedBlockArgument: 0.003378000
Lint/BadDirective: 0.002125000
Naming/VariableNames: 0.001809000
Lint/PercentArrays: 0.001708000
Layout/TrailingWhitespace: 0.001362000
Style/PercentLiteralDelimiters: 0.001342000
Lint/DuplicateWhenCondition: 0.001042000
Style/MultilineCurlyBlock: 0.001036000
Style/HeredocIndent: 0.000568000
Lint/AmbiguousAssignment: 0.000523000
Layout/TrailingBlankLines: 0.000478000
Metrics/CyclomaticComplexity: 0.000340000
Lint/DebugCalls: 0.000322000
Lint/NotNilAfterNoBang: 0.000304000
Lint/UselessConditionInWhen: 0.000292000
Lint/HashDuplicatedKey: 0.000287000
Lint/NotNil: 0.000285000
Performance/MinMaxAfterMap: 0.000280000
Lint/EmptyLoop: 0.000279000
Lint/EmptyEnsure: 0.000276000
Lint/DebuggerStatement: 0.000276000
Style/IsAFilter: 0.000272000
Lint/SignalTrap: 0.000262000
Performance/ChainedCallWithNoBang: 0.000261000
Lint/EmptyExpression: 0.000253000
Lint/LiteralsComparison: 0.000242000
Performance/ExcessiveAllocations: 0.000241000
Naming/AsciiIdentifiers: 0.000239000
Performance/FirstLastAfterFilter: 0.000238000
Lint/UnreachableCode: 0.000234000
Performance/CompactAfterMap: 0.000229000
Lint/LiteralAssignmentsInExpressions: 0.000227000
Performance/MapInsteadOfBlock: 0.000222000
Lint/RandZero: 0.000221000
Naming/AccessorMethodName: 0.000219000
Lint/ShadowedException: 0.000216000
Performance/FlattenAfterMap: 0.000215000
Lint/RequireParentheses: 0.000215000
Lint/VoidOutsideLib: 0.000215000
Performance/SizeAfterFilter: 0.000215000
Style/HeredocEscape: 0.000209000
Lint/LiteralInCondition: 0.000208000
Lint/RedundantWithObject: 0.000207000
Lint/RedundantWithIndex: 0.000206000
Style/NegatedConditionsInUnless: 0.000204000
Lint/LiteralInInterpolation: 0.000198000
Lint/RedundantStringCoercion: 0.000198000
Style/ParenthesesAroundCondition: 0.000195000
Lint/TrailingRescueException: 0.000193000
Naming/MethodNames: 0.000190000
Performance/AnyAfterFilter: 0.000187000
Naming/BlockParameterName: 0.000185000
Naming/BinaryOperatorParameterName: 0.000184000
Performance/AnyInsteadOfEmpty: 0.000182000
Lint/UnusedClassVariableAccess: 0.000181000
Naming/PredicateName: 0.000177000
Style/RedundantBegin: 0.000177000
Style/VerboseBlock: 0.000176000
Style/IsANil: 0.000172000
Naming/ConstantNames: 0.000172000
Style/UnlessElse: 0.000171000
Style/WhileTrue: 0.000166000
Naming/QueryBoolMethods: 0.000165000
Naming/TypeNames: 0.000162000
Lint/UnusedComparison: 0.000160000
Naming/RescuedExceptionsVariableName: 0.000160000
Style/RedundantNext: 0.000152000
Style/RedundantReturn: 0.000150000
Lint/UnusedGenericOrUnion: 0.000138000
Lint/UnusedInstanceVariableAccess: 0.000126000
Lint/UnusedLiteral: 0.000113000
Lint/UnusedLocalVariableAccess: 0.000111000
Lint/UnusedPseudoMethodCall: 0.000110000
Lint/UnusedSelfAccess: 0.000106000
Lint/DuplicatedRequire: 0.000004000
Naming/Filename: 0.000002000
Lint/Typos: 0.000002000
Lint/SpecFocus: 0.000001000
Lint/SpecFilename: 0.000001000
Benchmark diff

diff --git a/src/ameba/runner.cr b/src/ameba/runner.cr
index ebca6278..ed0c9d2a 100644
--- a/src/ameba/runner.cr
+++ b/src/ameba/runner.cr
@@ -138,12 +138,16 @@ module Ameba
         # We have to reprocess the source to pick up any changes. Since a
         # change could (theoretically) introduce syntax errors, we break the
         # loop if we find any.
+        start = Time.utc
         @syntax_rule.test(source)
+        puts "#{@syntax_rule.class.rule_name}: #{Time.utc - start}"
         break unless source.valid?
     @rules.each do |rule|
       next if rule.excluded?(source)
  •      start = Time.utc
         rule.test(source)
    
  •      puts "#{rule.class.rule_name}: #{Time.utc - start}"
       end
       check_unneeded_directives(source)
       break unless autocorrect? && source.correct?
    

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions